//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.Collections.Generic;
using System.Text;

namespace OpenLS.Spreadsheet.UI
{
    class RangeBuilder
    {
        public static Range GetRange(IEnumerable<Cell> cells)
        {
            var lCells = new List<Cell>(cells);
            if (lCells.Count == 0)
                return null;
            var table = new Dictionary<CellAddress, Cell>();
            foreach (var cell in lCells)
            {
                table.Add(cell.Address, cell);
            }
            var verticalRanges = new List<MultiCellsRange>();
            while (table.Count > 0)
            {
                Cell cell = Enumerable.FirstOrDefault(table.Values);
                int column = cell.Column.Index;
                int minRow = cell.Row.Index;
                int maxRow = minRow;
                while (true)
                {
                    if (minRow == 0)
                        break;
                    if (!table.ContainsKey(new CellAddress(minRow-1, column)))
                        break;
                    minRow--;
                }
                while (true)
                {
                    if (maxRow == Worksheet.MaxRowIndex)
                        break;
                    if (!table.ContainsKey(new CellAddress(maxRow+1, column)))
                        break;
                    maxRow++;
                }
                verticalRanges.Add(new MultiCellsRange(cell.Worksheet[minRow, column], cell.Worksheet[maxRow, column]));
                for (int i = minRow; i <= maxRow; i++)
                    table.Remove(new CellAddress(i, column));
            }
            var rangeTable = new Dictionary<CellAddress, MultiCellsRange>();
            foreach (var range in verticalRanges)
            {
                rangeTable.Add(range.TopLeftCell.Address, range);
            }
            var validRanges = new List<MultiCellsRange>();
            while (verticalRanges.Count > 0)
            {
                MultiCellsRange r = verticalRanges[0];
                int minColumn = r.TopLeftCell.Column.Index;
                int maxColumn = r.TopLeftCell.Column.Index;
                int row = r.TopLeftCell.Row.Index;
                while (true)
                {
                    if (minColumn == 0)
                        break;
                    var a = new CellAddress(row, minColumn- 1);
                    if (!rangeTable.ContainsKey(a))
                        break;
                    MultiCellsRange rr;
                    if (!rangeTable.TryGetValue(a, out rr))
                        break;
                    if (rr.ColumnSpan != r.ColumnSpan)
                        break;
                    minColumn--;
                }
                while (true)
                {
                    if (maxColumn == Worksheet.MaxColumnIndex)
                        break;
                    var a = new CellAddress(row, maxColumn+1);
                    if (!rangeTable.ContainsKey(a))
                        break;
                    MultiCellsRange rr;
                    if (!rangeTable.TryGetValue(a, out rr))
                        break;
                    if (rr.ColumnSpan != r.ColumnSpan)
                        break;
                    maxColumn++;
                }
                MultiCellsRange leftRange = rangeTable[new CellAddress(row, minColumn)];
                MultiCellsRange rightRange = rangeTable[new CellAddress(row, maxColumn)];
                var validRange = new MultiCellsRange(leftRange.TopLeftCell, rightRange.BottomRight);
                validRanges.Add(validRange);
                for (int column = minColumn ; column <= maxColumn; column++)
                {
                    verticalRanges.Remove(rangeTable[new CellAddress(row, column)]);
                }
            }
            if (validRanges.Count == 1)
                return validRanges[0];
            var cr = new List<SimpleRange>();
            foreach (var range in validRanges)
            {
                cr.Add(range);
            }
            return new CompositeRange(cr);

        }
    }
}
